package com.css.dynamic.rule;

import com.alibaba.nacos.client.naming.utils.RandomUtils;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * 基于客户端版本号灰度路由
 *
 * @description:
 * @author: guohui13
 * @date: 2022/8/19 17:24
 **/
@AllArgsConstructor
public class VersionGrayLoadBalancer implements GrayLoadBalancer {
    private DiscoveryClient discoveryClient;


    /**
     * 根据serviceId 筛选可用服务
     *
     * @param serviceId 服务ID
     * @param request   当前请求
     * @return
     */
    @Override
    public ServiceInstance choose(String serviceId, ServerHttpRequest request) {
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);

        //注册中心无实例 抛出异常
        if (CollectionUtils.isEmpty(instances)) {
            System.out.println(("No instance available for {}" + serviceId));
            ;
            throw new NotFoundException("No instance available for " + serviceId);
        }

        // 获取请求version，无则随机返回可用实例
        String reqVersion = request.getHeaders().getFirst("VERSION");
        if (StringUtils.isBlank(reqVersion)) {
            return instances.get(RandomUtils.nextInt(instances.size()));
        }

        // 遍历可以实例元数据，若匹配则返回此实例
        for (ServiceInstance instance : instances) {
            Map<String, String> metadata = instance.getMetadata();
//            String targetVersion = MapUtil.getStr(metadata, "VERSION");
            String targetVersion = metadata.get("VERSION");
            if (reqVersion.equalsIgnoreCase(targetVersion)) {
//                log.debug("gray requst match success :{} {}", reqVersion, instance);
                return instance;
            }
        }
//        return instances.get(RandomUtil.randomInt(instances.size()));
        return instances.get(RandomUtils.nextInt(instances.size()));
    }
}
